﻿#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <asm/io.h>

#include "button_drv.h"

/*
 * 2个button: GPIO5_IO01, GPIO1_IO18
 */

static volatile unsigned int *CCM_CCGR1                              ;
static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1;
static volatile unsigned int *GPIO5_GDIR                             ;
static volatile unsigned int *GPIO5_DR                               ;

static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B ;
static volatile unsigned int *GPIO1_GDIR                             ;
static volatile unsigned int *GPIO1_DR                               ;

static void board_demo_button_init (int which) /* 初始化button, which-哪个button */	   
{
	unsigned int val;

	//printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);
	if (!CCM_CCGR1)
	{
		CCM_CCGR1								= ioremap(0x20C406C, 4);
		IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = ioremap(0x229000C, 4);
		GPIO5_GDIR								= ioremap(0x020AC000 + 0x4, 4);
		GPIO5_DR								= ioremap(0x020AC000 + 0, 4);

		IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B       = ioremap(0x20E008C, 4);
		GPIO1_GDIR								= ioremap(0x0209C000 + 0x4, 4);
		GPIO1_DR								= ioremap(0x0209C000 + 0, 4);
	}

	if (which == 0)
	{
		/* a.1 使能GPIO5
		 * set CCM to enable GPIO5
		 * CCM_CCGR1[CG15] 0x20C406C
		 * bit[31:30] = 0b11
		 */
		*CCM_CCGR1 |= (3<<30);
		
		/* b.1 设置GPIO5_IO01用于GPIO
		 * set IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1
		 *		to configure GPIO5_IO01 as GPIO
		 * IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1	0x229000c
		 * bit[3:0] = 0b0101 alt5
		 */
		val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1;
		val &= ~(0xf);
		val |= (5);
		*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = val;		
		
		/* c.1 设置GPIO5_IO01作为input引脚
		 * set GPIO5_GDIR to configure GPIO5_IO01 as input
		 * GPIO5_GDIR  0x020AC000 + 0x4
		 * bit[1] = 0b0
		 */
		*GPIO5_GDIR &= ~(1<<1);
	}
	else if(which == 1)
	{
		/* a.2 使能GPIO1
		 * set CCM to enable GPIO1
		 * CCM_CCGR1[CG13] 0x20C406C
		 * bit[27:26] = 0b11
		 */
		*CCM_CCGR1 |= (3<<26);

		/* b.2 设置GPIO1_IO18用于GPIO
		 * set IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B 
		 *		to configure GPIO1_IO18 as GPIO
		 * IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B   0x20E008C
		 * bit[3:0] = 0b0101 alt5
		 */
		val = *IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B ;
		val &= ~(0xf);
		val |= (5);
		*IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B  = val;
		
		/* c.2 设置GPIO1_IO18作为input引脚
		 * set GPIO1_GDIR to configure GPIO1_IO18 as input
		 * GPIO1_GDIR  0x0209C000 + 0x4
		 * bit[18] = 0b0
		 */
		*GPIO1_GDIR &= ~(1<<18);
	}
			
}

static int board_demo_button_read (int which) /* 读button, which-哪个 */
{
	//printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");
	if (which == 0)
		return (*GPIO5_DR & (1<<1)) ? 1 : 0;
	else
		return (*GPIO1_DR & (1<<18)) ? 1 : 0;
}

static struct button_operations my_buttons_ops = {
	.count = 2,
	.init = board_demo_button_init,
	.read = board_demo_button_read,
};

int board_100ask_qemu_imx6ull_button_init(void)
{
	register_button_operations(&my_buttons_ops);
	return 0;
}

void board_100ask_qemu_imx6ull_button_exit(void)
{
	unregister_button_operations();
}

module_init(board_100ask_qemu_imx6ull_button_init);
module_exit(board_100ask_qemu_imx6ull_button_exit);

MODULE_LICENSE("GPL");

